"""
策略回测页面

提供完整的策略回测功能，包括策略选择、参数配置、回测执行和结果展示。

作者: AI Assistant
版本: 1.0.0
日期: 2025-01-06
"""

import streamlit as st
import pandas as pd
from datetime import datetime
import logging

from core import StockDataFetcher, TechnicalIndicators
from backtest import BacktestEngine
from backtest.visualization import BacktestVisualizer
from strategies import MAStrategy, BreakoutStrategy, RSIStrategy, MACDStrategy


def backtest_page(
    stock_input: str,
    strategy_name: str,
    strategy_params: dict,
    initial_capital: float,
    days: int,
    commission: float,
    slippage: float,
    run_backtest: bool
):
    """
    策略回测页面
    
    参数:
        stock_input: 股票代码或名称
        strategy_name: 策略名称
        strategy_params: 策略参数字典
        initial_capital: 初始资金
        days: 回测天数
        commission: 手续费率
        slippage: 滑点比例
        run_backtest: 是否开始回测
    """
    st.markdown("# 🎯 策略回测")
    st.markdown("使用历史数据验证交易策略的有效性")
    
    if not run_backtest:
        # 显示说明
        st.info("👈 请在左侧设置回测参数，然后点击'开始回测'按钮")
        
        # 显示策略说明
        with st.expander("📚 策略说明", expanded=True):
            if strategy_name == "均线交叉策略":
                st.markdown("""
                ### 均线交叉策略
                
                **原理：**
                - 使用两条不同周期的移动平均线
                - 短期均线上穿长期均线时买入（金叉）
                - 短期均线下穿长期均线时卖出（死叉）
                
                **优点：**
                - 简单易懂，操作清晰
                - 适合趋势明显的市场
                - 滞后性小，能及时捕捉趋势
                
                **缺点：**
                - 震荡市容易频繁交易
                - 可能产生假信号
                """)
            
            elif strategy_name == "突破策略":
                st.markdown("""
                ### 突破策略
                
                **原理：**
                - 价格突破N日最高价时买入
                - 价格跌破N日最低价时卖出
                
                **优点：**
                - 能捕捉强势突破行情
                - 顺势而为，止损明确
                
                **缺点：**
                - 假突破风险
                - 可能追高杀跌
                """)
            
            elif strategy_name == "RSI策略":
                st.markdown("""
                ### RSI超买超卖策略
                
                **原理：**
                - RSI低于超卖阈值时买入
                - RSI高于超买阈值时卖出
                
                **优点：**
                - 能识别超买超卖状态
                - 适合震荡市场
                
                **缺点：**
                - 趋势市场表现较差
                - 可能过早卖出或买入
                """)
            
            elif strategy_name == "MACD策略":
                st.markdown("""
                ### MACD策略
                
                **原理：**
                - MACD柱由负转正时买入（金叉）
                - MACD柱由正转负时卖出（死叉）
                
                **优点：**
                - 趋势跟踪能力强
                - 信号相对稳定
                
                **缺点：**
                - 有一定滞后性
                - 震荡市信号较多
                """)
        
        # 显示回测流程
        with st.expander("🔄 回测流程", expanded=False):
            st.markdown("""
            1. **数据获取** - 获取股票历史K线数据
            2. **策略初始化** - 根据参数初始化策略
            3. **回测执行** - 遍历历史数据，模拟交易
            4. **绩效计算** - 计算收益率、回撤、夏普比率等指标
            5. **结果展示** - 图表和数据展示回测结果
            """)
        
        return
    
    # 开始回测
    logger = logging.getLogger(__name__)
    
    try:
        # 第一步：获取股票数据
        with st.spinner("📊 正在获取股票数据..."):
            fetcher = StockDataFetcher()
            
            st.info(f"🔍 正在查找股票: {stock_input}")
            stock_code = fetcher.get_stock_code(stock_input)
            
            if not stock_code:
                st.error(f"❌ 未找到股票: {stock_input}")
                return
            
            st.success(f"✅ 找到股票代码: {stock_code}")
            
            # 获取历史数据
            st.info(f"📈 正在获取 {days} 天的历史数据...")
            hist_data = fetcher.get_historical_data(stock_code, period='daily', days=days)
            
            if hist_data is None or len(hist_data) == 0:
                st.error("❌ 无法获取历史数据")
                return
            
            st.success(f"✅ 历史数据获取成功: {len(hist_data)} 条记录")
        
        # 第二步：创建策略
        with st.spinner("⚙️ 正在初始化策略..."):
            strategy = None
            
            if strategy_name == "均线交叉策略":
                strategy = MAStrategy(**strategy_params)
            elif strategy_name == "突破策略":
                strategy = BreakoutStrategy(**strategy_params)
            elif strategy_name == "RSI策略":
                strategy = RSIStrategy(**strategy_params)
            elif strategy_name == "MACD策略":
                strategy = MACDStrategy(**strategy_params)
            
            if not strategy:
                st.error(f"❌ 未知的策略: {strategy_name}")
                return
            
            st.success(f"✅ 策略初始化成功: {strategy.name}")
            st.info(f"📝 策略参数: {strategy.get_params()}")
        
        # 第三步：执行回测
        with st.spinner("🚀 正在执行回测..."):
            engine = BacktestEngine(
                strategy=strategy,
                data=hist_data,
                initial_capital=initial_capital,
                commission=commission,
                slippage=slippage
            )
            
            result = engine.run()
            
            st.success("✅ 回测完成！")
        
        # 第四步：展示结果
        st.markdown("---")
        st.markdown("## 📊 回测结果")
        
        # 绩效指标
        visualizer = BacktestVisualizer(result, hist_data, strategy)
        performance = result['performance']
        
        visualizer.display_performance_metrics(performance)
        
        # 可视化图表
        st.markdown("---")
        st.markdown("## 📈 资金曲线")
        
        fig_equity = visualizer.plot_equity_curve()
        st.plotly_chart(fig_equity, use_container_width=True)
        
        st.markdown("---")
        st.markdown("## 📉 回撤分析")
        
        fig_drawdown = visualizer.plot_drawdown()
        st.plotly_chart(fig_drawdown, use_container_width=True)
        
        st.markdown("---")
        st.markdown("## 💹 价格与交易信号")
        
        fig_price = visualizer.plot_price_with_signals()
        st.plotly_chart(fig_price, use_container_width=True)
        
        st.markdown("---")
        st.markdown("## 📋 交易记录")
        
        visualizer.display_trades_table(result['trades'])
        
        # 数据下载
        st.markdown("---")
        st.markdown("## 📥 数据导出")
        
        col1, col2 = st.columns(2)
        
        with col1:
            # 导出交易记录
            if result['trades']:
                trades_df = pd.DataFrame(result['trades'])
                csv = trades_df.to_csv(index=False, encoding='utf-8-sig')
                st.download_button(
                    label="📊 下载交易记录（CSV）",
                    data=csv,
                    file_name=f"backtest_trades_{stock_code}_{datetime.now().strftime('%Y%m%d')}.csv",
                    mime="text/csv"
                )
        
        with col2:
            # 导出资金曲线
            equity_csv = result['equity_curve'].to_csv(encoding='utf-8-sig')
            st.download_button(
                label="📈 下载资金曲线（CSV）",
                data=equity_csv,
                file_name=f"backtest_equity_{stock_code}_{datetime.now().strftime('%Y%m%d')}.csv",
                mime="text/csv"
            )
        
        # 回测总结
        st.markdown("---")
        st.markdown("## 📝 回测总结")
        
        col1, col2, col3 = st.columns(3)
        
        with col1:
            st.markdown("### 收益情况")
            total_return = performance['总收益率']
            if total_return > 0:
                st.success(f"✅ 盈利 {total_return:.2f}%")
            else:
                st.error(f"❌ 亏损 {abs(total_return):.2f}%")
        
        with col2:
            st.markdown("### 风险评估")
            sharpe = performance['夏普比率']
            if sharpe > 2:
                st.success(f"✅ 优秀 (夏普: {sharpe:.2f})")
            elif sharpe > 1:
                st.info(f"ℹ️ 良好 (夏普: {sharpe:.2f})")
            else:
                st.warning(f"⚠️ 一般 (夏普: {sharpe:.2f})")
        
        with col3:
            st.markdown("### 交易效率")
            win_rate = performance['胜率']
            if win_rate > 60:
                st.success(f"✅ 高胜率 {win_rate:.2f}%")
            elif win_rate > 40:
                st.info(f"ℹ️ 中等胜率 {win_rate:.2f}%")
            else:
                st.warning(f"⚠️ 低胜率 {win_rate:.2f}%")
        
        # 策略建议
        with st.expander("💡 策略优化建议", expanded=False):
            st.markdown("### 根据回测结果，给出以下建议：")
            
            # 根据结果给出建议
            suggestions = []
            
            if total_return < 0:
                suggestions.append("- ⚠️ 策略在回测期内亏损，建议调整参数或更换策略")
            
            if performance['最大回撤'] < -20:
                suggestions.append("- ⚠️ 最大回撤超过20%，风险较高，建议增加止损机制")
            
            if performance['胜率'] < 40:
                suggestions.append("- ⚠️ 胜率较低，可能存在频繁止损，建议优化入场条件")
            
            if performance['盈亏比'] < 1:
                suggestions.append("- ⚠️ 盈亏比小于1，平均盈利小于平均亏损，建议优化止盈止损比例")
            
            if performance['交易次数'] < 5:
                suggestions.append("- ℹ️ 交易次数较少，样本不足，建议延长回测周期或调整参数")
            
            if performance['交易次数'] > 100:
                suggestions.append("- ⚠️ 交易次数过多，可能存在过度交易，手续费成本高")
            
            if sharpe > 2 and total_return > 20:
                suggestions.append("- ✅ 策略表现优秀，风险调整收益良好")
            
            if not suggestions:
                suggestions.append("- ✅ 策略表现正常，继续观察")
            
            for suggestion in suggestions:
                st.markdown(suggestion)
        
        logger.info(f"回测完成 - {stock_code} - {strategy_name}")
        
    except Exception as e:
        st.error(f"❌ 回测过程出错: {str(e)}")
        logger.error(f"回测错误: {e}", exc_info=True)
        
        with st.expander("查看错误详情"):
            import traceback
            st.code(traceback.format_exc())

